﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using EFRebinder;
using KVP;
namespace FastDatabaseQuery
{
   public class FindInDatabase<T> : FindHelper<T> 
        where T: class
    {

        public FindInDatabase(ColList<T> col):base(col)
        {
                
        }

        //http://blogs.msdn.com/b/alexj/archive/2009/03/26/tip-8-writing-where-in-style-queries-using-linq-to-entities.aspx
     //   public static Expression<Func<TElement, bool>> BuildOrExpression<TElement, TValue>(
     //    Expression<Func<TElement, TValue>> valueSelector,
     //    IEnumerable<TValue> values
     //)
     //   {
     //       if (null == valueSelector)
     //           throw new ArgumentNullException("valueSelector");

     //       if (null == values)
     //           throw new ArgumentNullException("values");

     //       ParameterExpression p = valueSelector.Parameters.Single();

     //       if (!values.Any())
     //           return e => false;

     //       var equals = values.Select(value =>
     //           (Expression)Expression.Equal(
     //                valueSelector.Body,
     //                Expression.Constant(
     //                    value,
     //                    typeof(TValue)
     //                )
     //           )
     //       );
     //       var body = equals.Aggregate<Expression>(
     //                (accumulate, equal) => Expression.Or(accumulate, equal)
     //        );

     //       return Expression.Lambda<Func<TElement, bool>>(body, p);
     //   }

        //http://social.msdn.microsoft.com/forums/en-US/adodotnetentityframework/thread/095745fe-dcf0-4142-b684-b7e4a1ab59f0/
        protected internal Expression<Func<T1, bool>> BuildContainsExpression<T1, TValue>(
    
        Expression<Func<T1, TValue>> valueSelector, IEnumerable<TValue> values)
    
    {
    
        if (null == valueSelector) { throw new ArgumentNullException("valueSelector"); }
    
        if (null == values) { throw new ArgumentNullException("values"); }
    
        ParameterExpression p = valueSelector.Parameters.Single();
    
        // p => valueSelector(p) == values[0] || valueSelector(p) == ...
    
        if (!values.Any())
    
        {
    
            return e => false;
    
        }
    
        var equals = values.Select(item => (Expression)Expression.Equal(valueSelector.Body, Expression.Constant(item, typeof(TValue))));
    
        var body = equals.Aggregate<Expression>((accumulate, equal) => Expression.Or(accumulate, equal));
    
        return Expression.Lambda<Func<T1, bool>>(body, p);
    
    }

       
        public virtual void LoadFromQueryable(IQueryable<T> iq)
        {
            if(iq == null)
                return;
            foreach(var item in iq)
            {
                ColToLoad.Add(item);
            }
        }
        public virtual IQueryable<T> LoadAllQ()
        {
            return ColToLoad.SelfObjectSet;        
        }
        public virtual void LoadAll()
        {
            LoadFromQueryable(ColToLoad.SelfObjectSet);        
        }
        public KVPNew<U, Q>[] LoadFast2Props<U, Q>(IQueryable<T> iq, string Key, string Value)
        {
            return iq.Project().ToKVP<U, Q>(Key,Value).ToArray();
        }
        public KVPNew<long, string>[] LoadFast2PropsLongString(IQueryable<T> iq, string Key, string Value)
        {
            return LoadFast2Props<long, string>(iq, Key, Value);
        }
        
    }
}
